home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1988-1991 Apple Computer, Inc.
- * All Rights Reserved.
- *
- * Warranty Information
- * Even though Apple has reviewed this software, Apple makes no warranty
- * or representation, either express or implied, with respect to this
- * software, its quality, accuracy, merchantability, or fitness for a
- * particular purpose. As a result, this software is provided "as is,"
- * and you, its user, are assuming the entire risk as to its quality
- * and accuracy.
- *
- * This code may be used and freely distributed as long as it includes
- * this copyright notice and the warranty information.
- *
- *
- * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc)
- * pack bytes from high to low (they are big-endian).
- * Use the HighLow routines to match the native format
- * of these machines.
- *
- * Intel-like machines (PCs, Sequent)
- * pack bytes from low to high (the are little-endian).
- * Use the LowHigh routines to match the native format
- * of these machines.
- *
- * These routines have been tested on the following machines:
- * Apple Macintosh, MPW 3.1 C compiler
- * Apple Macintosh, THINK C compiler
- * Silicon Graphics IRIS, MIPS compiler
- * Cray X/MP and Y/MP
- * Digital Equipment VAX
- *
- *
- * Implemented by Malcolm Slaney and Ken Turkowski.
- *
- * Malcolm Slaney contributions during 1988-1990 include big- and little-
- * endian file I/O, conversion to and from Motorola's extended 80-bit
- * floating-point format, and conversions to and from IEEE single-
- * precision floating-point format.
- *
- * In 1991, Ken Turkowski implemented the conversions to and from
- * IEEE double-precision format, added more precision to the extended
- * conversions, and accommodated conversions involving +/- infinity,
- * NaN's, and denormalized numbers.
- *
- * $Id: portableio.c,v 1.11 2001/01/07 23:47:38 markt Exp $
- */
-
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #if defined(__riscos__) && defined(FPA10)
- #include "ymath.h"
- #else
- #include <math.h>
- #endif
- #include "portableio.h"
-
- #ifdef WITH_DMALLOC
- #include <dmalloc.h>
- #endif
-
- /****************************************************************
- * Big/little-endian independent I/O routines.
- ****************************************************************/
-
- /*
- * It is a hoax to call this code portable-IO:
- *
- * - It doesn't work on machines with CHAR_BIT != 8
- * - it also don't test this error condition
- * - otherwise it tries to handle CHAR_BIT != 8 by things like
- * masking 'putc(i&0xff,fp)'
- * - It doesn't handle EOF in any way
- * - it only works with ints with 32 or more bits
- * - It is a collection of initial buggy code with patching the known errors
- * instead of CORRECTING them!
- * For that see comments on the old Read16BitsHighLow()
- */
-
- #ifdef KLEMM_36
-
- signed int ReadByte ( FILE* fp )
- {
- int result = getc (fp);
- return result == EOF ? 0 : (signed char) (result & 0xFF);
- }
-
- unsigned int ReadByteUnsigned ( FILE* fp )
- {
- int result = getc (fp);
- return result == EOF ? 0 : (unsigned char) (result & 0xFF);
- }
-
- #else
-
- int
- ReadByte(FILE *fp)
- {
- int result;
-
- result = getc(fp) & 0xff;
- if (result & 0x80)
- result = result - 0x100;
- return result;
- }
-
- #endif
-
- #ifdef KLEMM_36
-
- int Read16BitsLowHigh ( FILE* fp )
- {
- int low = ReadByteUnsigned (fp);
- int high = ReadByte (fp);
-
- return (high << 8) | low;
- }
-
- #else
- int
- Read16BitsLowHigh(FILE *fp)
- {
- int first, second, result;
-
- first = 0xff & getc(fp);
- second = 0xff & getc(fp);
-
- result = (second << 8) + first;
- #ifndef THINK_C42
- if (result & 0x8000)
- result = result - 0x10000;
- #endif /* THINK_C */
- return(result);
- }
- #endif
-
-
- #ifdef KLEMM_36
-
- int Read16BitsHighLow ( FILE* fp )
- {
- int high = ReadByte (fp);
- int low = ReadByteUnsigned (fp);
-
- return (high << 8) | low;
- }
-
- #else
- int
- Read16BitsHighLow(FILE *fp)
- {
- int first, second, result;
-
- /* Reads the High bits, the value is -128...127
- * (which gave after upscaling the -32768...+32512
- * Why this value is not converted to signed char?
- */
- first = 0xff & getc(fp);
- /* Reads the Lows bits, the value is 0...255
- * This is correct. This value gives an additional offset
- * for the High bits
- */
- second = 0xff & getc(fp);
-
- /* This is right */
- result = (first << 8) + second;
-
- /* Now we are starting to correct the nasty bug of the first instruction
- * The value of the high bits is wrong. Always. So we must correct this
- * value. This seems to be not necessary for THINK_C42. This is either
- * a 16 bit compiler with 16 bit ints (where this bug is hidden and 0x10000
- * is not in the scope of an int) or it is not a C compiler, but only a
- * C like compiler. In the first case the '#ifndef THINK_C42' is wrong
- * because it's not a property of the THINK_C42 compiler, but of all compilers
- * with sizeof(int)*CHAR_BIT < 18.
- * Another nasty thing is that the rest of the code doesn't work for 16 bit ints,
- * so this patch don't solve the 16 bit problem.
- */
- #ifndef THINK_C42
- if (result & 0x8000)
- result = result - 0x10000;
- #endif /* THINK_C */
- return(result);
- }
- #endif
-
- void
- Write8Bits(FILE *fp, int i)
- {
- putc(i&0xff,fp);
- }
-
-
- void
- Write16BitsLowHigh(FILE *fp, int i)
- {
- putc(i&0xff,fp);
- putc((i>>8)&0xff,fp);
- }
-
-
- void
- Write16BitsHighLow(FILE *fp, int i)
- {
- putc((i>>8)&0xff,fp);
- putc(i&0xff,fp);
- }
-
- #ifdef KLEMM_36
-
- int Read24BitsHighLow ( FILE* fp )
- {
- int high = ReadByte (fp);
- int med = ReadByteUnsigned (fp);
- int low = ReadByteUnsigned (fp);
-
- return (high << 16) | (med << 8) | low;
- }
-
- #else
- int
- Read24BitsHighLow(FILE *fp)
- {
- int first, second, third;
- int result;
-
- first = 0xff & getc(fp);
- second = 0xff & getc(fp);
- third = 0xff & getc(fp);
-
- result = (first << 16) + (second << 8) + third;
- if (result & 0x800000)
- result = result - 0x1000000;
- return(result);
- }
- #endif
-
- #define Read32BitsLowHigh(f) Read32Bits(f)
-
- #ifdef KLEMM_36
-
- int Read32Bits ( FILE* fp )
- {
- int low = ReadByteUnsigned (fp);
- int medl = ReadByteUnsigned (fp);
- int medh = ReadByteUnsigned (fp);
- int high = ReadByte (fp);
-
- return (high << 24) | (medh << 16) | (medl << 8) | low;
- }
-
- #else
-
- int
- Read32Bits(FILE *fp)
- {
- int first, second, result;
-
- first = 0xffff & Read16BitsLowHigh(fp);
- second = 0xffff & Read16BitsLowHigh(fp);
-
- result = (second << 16) + first;
- #ifdef CRAY
- if (result & 0x80000000)
- result = result - 0x100000000;
- #endif /* CRAY */
- return(result);
- }
- #endif
-
-
- #ifdef KLEMM_36
-
- int Read32BitsHighLow ( FILE* fp )
- {
- int high = ReadByte (fp);
- int medh = ReadByteUnsigned (fp);
- int medl = ReadByteUnsigned (fp);
- int low = ReadByteUnsigned (fp);
-
- return (high << 24) | (medh << 16) | (medl << 8) | low;
- }
-
- #else
-
- int
- Read32BitsHighLow(FILE *fp)
- {
- int first, second, result;
-
- first = 0xffff & Read16BitsHighLow(fp);
- second = 0xffff & Read16BitsHighLow(fp);
-
- result = (first << 16) + second;
- #ifdef CRAY
- if (result & 0x80000000)
- result = result - 0x100000000;
- #endif
- return(result);
- }
-
- #endif
-
- void
- Write32Bits(FILE *fp, int i)
- {
- Write16BitsLowHigh(fp,(int)(i&0xffffL));
- Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
- }
-
-
- void
- Write32BitsLowHigh(FILE *fp, int i)
- {
- Write16BitsLowHigh(fp,(int)(i&0xffffL));
- Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
- }
-
-
- void
- Write32BitsHighLow(FILE *fp, int i)
- {
- Write16BitsHighLow(fp,(int)((i>>16)&0xffffL));
- Write16BitsHighLow(fp,(int)(i&0xffffL));
- }
-
- #ifdef KLEMM_36
- void ReadBytes (FILE *fp, char *p, int n)
- {
- memset ( p, 0, n );
- fread ( p, 1, n, fp );
- }
- #else
- void ReadBytes(FILE *fp, char *p, int n)
- {
- /* What about fread? */
-
- while (!feof(fp) & (n-- > 0))
- *p++ = getc(fp);
- }
- #endif
-
- void ReadBytesSwapped(FILE *fp, char *p, int n)
- {
- register char *q = p;
-
- /* What about fread? */
-
- while (!feof(fp) & (n-- > 0))
- *q++ = getc(fp);
-
- /* If not all bytes could be read, the resorting is different
- * from the normal resorting. Is this intention or another bug?
- */
- for (q--; p < q; p++, q--){
- n = *p;
- *p = *q;
- *q = n;
- }
- }
-
- #ifdef KLEMM_36
- void WriteBytes(FILE *fp, char *p, int n)
- {
- /* return n == */
- fwrite ( p, 1, n, fp );
- }
- #else
- void WriteBytes(FILE *fp, char *p, int n)
- {
- /* No error condition checking */
- while (n-- > 0)
- putc(*p++, fp);
- }
- #endif
- #ifdef KLEMM_36
- void WriteBytesSwapped(FILE *fp, char *p, int n)
- {
- p += n;
- while ( n-- > 0 )
- putc ( *--p, fp );
- }
- #else
- void WriteBytesSwapped(FILE *fp, char *p, int n)
- {
- p += n-1;
- while (n-- > 0)
- putc(*p--, fp);
- }
- #endif
-
-
-
- /****************************************************************
- * The following two routines make up for deficiencies in many
- * compilers to convert properly between unsigned integers and
- * floating-point. Some compilers which have this bug are the
- * THINK_C compiler for the Macintosh and the C compiler for the
- * Silicon Graphics MIPS-based Iris.
- ****************************************************************/
-
- #ifdef applec /* The Apple C compiler works */
- # define FloatToUnsigned(f) ((unsigned long)(f))
- # define UnsignedToFloat(u) ((double)(u))
- #else /* applec */
- # define FloatToUnsigned(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
- # define UnsignedToFloat(u) (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)
- #endif /* applec */
- /****************************************************************
- * Extended precision IEEE floating-point conversion routines
- ****************************************************************/
-
- double
- ConvertFromIeeeExtended(char* bytes)
- {
- double f;
- long expon;
- unsigned long hiMant, loMant;
-
- #ifdef TEST
- printf("ConvertFromIEEEExtended(%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx\r",
- (long)bytes[0], (long)bytes[1], (long)bytes[2], (long)bytes[3],
- (long)bytes[4], (long)bytes[5], (long)bytes[6],
- (long)bytes[7], (long)bytes[8], (long)bytes[9]);
- #endif
-
- expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
- hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
- | ((unsigned long)(bytes[3] & 0xFF) << 16)
- | ((unsigned long)(bytes[4] & 0xFF) << 8)
- | ((unsigned long)(bytes[5] & 0xFF));
- loMant = ((unsigned long)(bytes[6] & 0xFF) << 24)
- | ((unsigned long)(bytes[7] & 0xFF) << 16)
- | ((unsigned long)(bytes[8] & 0xFF) << 8)
- | ((unsigned long)(bytes[9] & 0xFF));
-
- /* This case should also be called if the number is below the smallest
- * positive double variable */
- if (expon == 0 && hiMant == 0 && loMant == 0) {
- f = 0;
- }
- else {
- /* This case should also be called if the number is too large to fit into
- * a double variable */
-
- if (expon == 0x7FFF) { /* Infinity or NaN */
- f = HUGE_VAL;
- }
- else {
- expon -= 16383;
- f = ldexp(UnsignedToFloat(hiMant), (int) (expon -= 31));
- f += ldexp(UnsignedToFloat(loMant), (int) (expon -= 32));
- }
- }
-
- if (bytes[0] & 0x80)
- return -f;
- else
- return f;
- }
-
-
-
-
-
- double
- ReadIeeeExtendedHighLow(FILE *fp)
- {
- char bytes [10];
-
- ReadBytes ( fp, bytes, 10 );
- return ConvertFromIeeeExtended ( bytes );
- }
-
-